#region License, Terms and Conditions
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Jayrock;
using pesta.Data;
using Pesta.DataAccess;
using Pesta.DataAccess.SqlServer;
using Pesta.Engine.social.spi;
using Pesta.DataAccess.Azure;
using raya.Library;

namespace raya.Models.activities
{
    public class ActivityRaya
    {
        public Activity act { get; set; }
        public string posterName { get; set; }
    }

    public class activities : Model
    {
#if AZURE
        public void add_activity(string creator, string appid, string title, string body)
        {
            using (var db = RayaDataContext.DB())
            {
                var time = UnixTime.ToInt64(DateTime.UtcNow);
                var act = new ActivityRow(creator, time.ToString())
                {
                    person_id = creator,
                    app_id = "",
                    title = title,
                    body = "",
                    created = time
                };
                db.InsertOnSubmit(AzureRayaDataContext.TableNames.activities, act);
                db.SubmitChanges();
            }
        }

        public void addNewFriendActivity(string friendId, string id)
        {
            using (var db = RayaDataContext.DB())
            {
                // We want to create the friend activities on both people so we do this twice
                Dictionary<string, string> values = new Dictionary<string, string> { { friendId, id }, { id, friendId } };
                foreach (var pair in values)
                {
                    string key = pair.Key;
                    string val = pair.Value;
                    var persons = db.persons.Where(p => p.id == key);
                    foreach (var p in persons)
                    {
                        string title = ("and <a href=\"/profile/" + key + "\" rel=\"friend\">" +
                                        p.first_name + " " + p.last_name + "</a> are now friends.");
                        add_activity(val, "", title, "");
                    }
                }
                db.SubmitChanges();
            }
        }

        public List<ActivityRaya> get_person_activities(string pid, int limit, string personName)
        {
            var data = new List<ActivityRaya>();
            List<Activity> activities;
            var options = new CollectionOptions();
            options.setMax(limit);
            using (var db = new AzureDbFetcher())
            {
                var ids = new HashSet<string> {pid};
                activities = db.GetActivities(ids, "", null, options);
            }
            foreach (var row in activities)
            {
                var actRaya = new ActivityRaya
                                  {
                                      act = row, 
                                      posterName = personName
                                  };
                data.Add(actRaya);
            }
            return data;
        }
#else
        public List<ActivityRaya> get_person_activities(int pid, int limit)
	    {
	        object data;
            if (!TryGetCache("activities", pid.ToString(), out data))
            {
                add_dependency("activities", pid.ToString(), null);
                using (var db = RayaDataContext.DB())
                {
                    var results = from act in db.activities
                                  from per in db.persons
                                  join app in db.applications on act.app_id equals app.id into aa
                                  from a in aa.DefaultIfEmpty()
                                  where act.person_id == pid && act.person_id == per.id && !act.title.Contains("[ACT")
                                  select new ActivityRaya()
                                             {
                                                 act =
                                                     new Activity()
                                                         {
                                                             title = act.title,
                                                             body = act.body,
                                                             postedTime = act.created,
                                                             userId = per.id.ToString(),
                                                             appId = a.id.ToString(),
                                                             streamTitle = a.title,
                                                             url = a.url,
                                                             id = act.id.ToString(),
                                                             mediaItems = db.activity_media_items
                                                                  .Where(x => x.activity_id == act.id)
                                                                  .Select(x => new MediaItem
                                                                    {
                                                                        mimeType = x.mime_type,
                                                                        type = (MediaItem.Type)Enum.Parse(typeof(MediaItem.Type), x.media_type),
                                                                        url = x.url
                                                                    })
                                                                    .ToList()
                                                         },
                                                 posterName = per.first_name + " " + per.last_name
                                             };
                                   
                    if (limit !=0)
                    {
                        results = results.Take(limit);
                    }
                    var ordered = results.OrderByDescending(u => u.act.postedTime);
                    if (results.Count() != 0)
                    {
                        foreach (var result in ordered)
                        {
                            add_dependency("activities", result.act.userId, "activities_res:" + pid);
                        }
                    }
                    data = ordered.ToList();
                    Insert("activities", pid.ToString(), data);
                }
            }
            return (List<ActivityRaya>)data;
	    }

        private static List<MediaItem> load_media_items(int activityId)
	    {
            List<MediaItem> mediaItems = new List<MediaItem>();
            using (var db = RayaDataContext.DB())
            {
                var results = from a in db.activity_media_items
                              where a.activity_id == activityId
                              select a;
                foreach (var result in results)
                {
                    MediaItem item = new MediaItem();
                    item.mimeType = result.mime_type;
                    item.type = (MediaItem.Type)Enum.Parse(typeof(MediaItem.Type), result.media_type);
                    item.url = result.url;
                    mediaItems.Add(item);
                }
            }
            return mediaItems;
	    }

        public List<ActivityRaya> get_friend_activities(int pid, int limit)
	    {
            object data;
            if (!TryGetCache("activities", pid.ToString(), out data))
            {
                add_dependency("activities", pid.ToString(), null);
                using (var db = RayaDataContext.DB())
                {
                    var results = from act in db.activities
                                  from per in db.persons
                                  join app in db.applications on act.app_id equals app.id into aa
                                  from a in aa.DefaultIfEmpty()
                                  where
                                      (db.friends.Where(x => x.friend_id == pid).Select(x => x.person_id).Contains(
                                           act.person_id) ||
                                       db.friends.Where(x => x.person_id == pid).Select(x => x.friend_id).Contains(
                                           act.person_id))
                                      && act.person_id == per.id && !act.title.Contains("[ACT")
                                  select new ActivityRaya()
                                             {
                                                 act = new Activity()
                                                           {
                                                               title = act.title, 
                                                              body = act.body, 
                                                             postedTime = act.created, 
                                                           userId  = per.id.ToString(),
                                                               appId   = a.id.ToString(),
                                                                 streamTitle = a.title, 
                                                                url = a.url,
                                                                id = a.id.ToString(),
                                                                mediaItems =  a != null
                                                                      ? load_media_items(a.id)
                                                                      : new List<MediaItem>(),
                                                           },
                                                 posterName = per.first_name + " " + per.last_name
                                             };
                    if (limit != 0)
                    {
                        results = results.Take(limit);
                    }
                    var ordered = results.OrderByDescending(x => x.act.postedTime);
                    foreach (var result in ordered)
                    {
                        add_dependency("activities", result.act.userId, "activities_res:" + pid);
                    }
                    data = ordered.ToList();
                    Insert("activities", pid.ToString(), data);
                }
            }
            return (List<ActivityRaya>)data;
	    }

        public void addNewFriendActivity(int friendId, int id)
        {
            using (var db = RayaDataContext.DB())
            {
                // We want to create the friend activities on both people so we do this twice
                Dictionary<int, int> values = new Dictionary<int, int> { { friendId, id }, { id, friendId } };
                foreach (var pair in values)
                {
                    int key = pair.Key;
                    int val = pair.Value;
                    var names = from p in db.persons
                                where p.id == key
                                select new
                                {
                                    name = p.first_name + " " + p.last_name
                                };
                    foreach (var n in names)
                    {
                        string title = ("and <a href=\"/profile/" + key + "\" rel=\"friend\">" +
                                        n.name + "</a> are now friends.");
                        add_activity(val, 0, title, "");
                    }
                    invalidate_dependency("activities", key.ToString());
                }
                db.SubmitChanges();
            }
        }
        public void add_activity(int creator, int appid, string title, string body)
        {
            using (var db = RayaDataContext.DB())
            {
                var act = new activity
                {
                    person_id = creator,
                    app_id = 0,
                    title = title,
                    body = "",
                    created = UnixTime.ToInt64(DateTime.UtcNow)
                };
                db.activities.InsertOnSubmit(act);
                db.SubmitChanges();
            }
        }
#endif

        
    }
}
